package com.iflytek.autofly.setting.biz.system;

import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;

import com.iflytek.autofly.radioservice.util.IRadioListener;
import com.iflytek.autofly.radioservice.util.RadioManager;
import com.iflytek.autofly.radioservice.util.RadioServiceCons;
import com.iflytek.autofly.utils.FlyLog;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

public class FlyRadioManager implements IRadioListener {

    private static final String TAG = "FlyRadioManager";
    private static final int MSG_TODO_START = 0x1001;
    private AtomicInteger mServiceReady = new AtomicInteger(0);
    private RadioManager mMngr;
    private IFlyRadioListener mListener;
    private BlockingQueue<Runnable> mTodoList = new LinkedBlockingQueue<>();
    private HandlerThread mTodoHandlerThread;
    private Handler mTodoHandler;

    private FlyRadioManager() {
    }

    public static FlyRadioManager registerListener(Context ctx, IFlyRadioListener l) {
        Singleton.INST.init(ctx, l);
        return Singleton.INST;
    }

    public static void unregisterListener() {
        Singleton.INST.fini();
    }

    @Override
    public void onScanFrequency(int i, boolean b) {
    }

    @Override
    public void onStateChange(int i) {
    }

    @Override
    public void onBandChange(int i) {
    }

    @Override
    public void onServiceStatusChanged(int status) {
        switch (status) {
            case RadioServiceCons.AidlStatus.SERVICE_AIDL_BOUND:
                FlyLog.d(TAG, "SERVICE_AIDL_BOUND");
                doInit();
                break;

            case RadioServiceCons.AidlStatus.SERVICE_AIDL_NOT_BOUND:
                FlyLog.e(TAG, "SERVICE_AIDL_NOT_BOUND");
                break;
        }

    }

    private void init(Context ctx, IFlyRadioListener l) {
        if (l == null) {
            FlyLog.e(TAG, "invalid IFlyRadioListener");
        }
        mMngr = RadioManager.registerListener(ctx, this);
        mListener = l;
        doInit();
    }

    private void doInit() {
        if (mServiceReady.incrementAndGet() < 2) {
            return;
        }
        initPending();
        if (!mTodoList.isEmpty()) {
            mTodoHandler.sendEmptyMessage(MSG_TODO_START);
        }
    }

    private void fini() {
        RadioManager.unregisterListener(this);
        mServiceReady.set(0);
    }

    public void getMode() {
        if (mServiceReady.getAndIncrement() < 2) {
            FlyLog.d(TAG, "pendding task");
            penddingTask(new Runnable() {
                @Override
                public void run() {
                    getMode();
                }
            });
            return;
        }
        int mode = mMngr.getRadioMode();
        FlyLog.d(TAG, "mode=" + mode);
        mListener.onModeChanged(mode);
    }

    public void setMode(final int mode) {
        if (mServiceReady.getAndIncrement() < 2) {
            FlyLog.d(TAG, "pendding task");
            penddingTask(new Runnable() {
                @Override
                public void run() {
                    setMode(mode);
                }
            });
            return;
        }
        FlyLog.d(TAG, "mode=" + mode);
        mMngr.switchRadioMode(mode);
    }

    private void penddingTask(Runnable runnable) {
        initPending();
        mTodoList.add(runnable);
    }

    private void initPending() {
        if (mTodoHandlerThread == null) {
            mTodoHandlerThread = new HandlerThread("todo");
            mTodoHandlerThread.start();
            mTodoHandler = new Handler(mTodoHandlerThread.getLooper(), new Handler.Callback() {
                @Override
                public boolean handleMessage(Message msg) {
                    if (msg.what == MSG_TODO_START) {
                        while (!mTodoList.isEmpty()) {
                            Runnable r = null;
                            try {
                                r = mTodoList.take();
                                r.run();
                            } catch (InterruptedException e) {
                                FlyLog.e(TAG, e);
                            }
                        }
                    }
                    return true;
                }
            });
        }

    }

    public interface IFlyRadioListener {
        void onModeChanged(int mode);
    }

    private static class Singleton {
        static FlyRadioManager INST = new FlyRadioManager();
    }

}
